package string 
{
	import flash.display.LineScaleMode;
	/**
	 * ...
	 * @author gcxk721
	 */
	public final class StringUtils 
	{
		
		public function StringUtils() 
		{
			
		}
		
		/**
		 * 返回第一次出现后,他把这一切都所提供的字符在串。
		 * @param	p_string
		 * @param	p_char
		 * @return
		 */
		public static function afterFirst(p_string : String, p_char : String) : String
		{
			if (p_string == null) 
			{
				return "";
			}
			var idx : int = p_string.indexOf(p_char);
			if (idx == -1) 
			{
				return "";
			}
			idx += p_char.length;
			return p_string.substr(idx);
		}
		
		/**
		 * 最后返回后,他把这一切都发生在p_string所提供的特征。
		 * @param	p_string
		 * @param	p_char
		 * @return
		 */
		public static function afterLast(p_string : String, p_char : String) : String
		{
			if (p_string == null) 
			{
				return "";
			}
			var idx : int = p_string.lastIndexOf(p_char);
			if (idx == -1) 
			{
				return "";
			}
			idx += p_char.length;
			return p_string.substr(idx);
		}
		
		/**
		 * 决定是否这个字符串从指定的前缀。
		 * @param	p_string
		 * @param	p_begin
		 * @return
		 */
		public static function beginsWith(p_string : String, p_begin : String) : Boolean
		{
			if (p_string == null) 
			{ 
				return false; 
			}
			return p_string.indexOf(p_begin) == 0;
		}
		
		/**
		 * 返回第一次出现之前把一切所提供的字符在串。
		 * @param	p_string
		 * @param	p_char
		 * @return
		 */
		public static function beforeFirst(p_string : String, p_char : String) : String
		{
			if (p_string == null) 
			{
				return "";
			}
			var idx:int = p_string.indexOf(p_char);
			if (idx == -1)
			{
				return "";
			}
			return p_string.substr(0, idx);
		}
		
		/**
		 * 返回的最后出现之前把一切所提供的字符在串。
		 * @param	p_string
		 * @param	p_char
		 * @return
		 */
		public static function beforeLast(p_string : String, p_char : String) : String
		{
			if (p_string == null) 
			{
				return "";
			}
			var idx:int = p_string.lastIndexOf(p_char);
			if (idx == -1)
			{
				return "";
			}
			return p_string.substr(0, idx);
		}
		
		/**
		 * 返回后,他把这一切都p_start第一的出现之前,在第一次出现的p_string p_end。
		 * @param	p_string
		 * @param	p_start
		 * @param	p_end
		 * @return
		 */
		public static function between(p_string : String, p_start : String, p_end : String) : String
		{
			var str:String = '';
			if (p_string == null)
			{
				return str;
			}
			var startIdx : int = p_string.indexOf(p_start);
			if (startIdx != -1)
			{
				startIdx += p_start.length; // RM: should we support multiple chars? (or ++startIdx);
				var endIdx:int = p_string.indexOf(p_end, startIdx);
				if (endIdx != -1) 
				{
					str = p_string.substr(startIdx, endIdx-startIdx);
				}
			}
			return str;
		}
		
		/**
		 * 描述、实用方法,明智的字符串分割,使您能够创造块的可读文本。该方法将返回你尽可能密切配合的p_delim paramater的,
		 * 在保持在p_len paramter文本的长度。
		 * 如果一场比赛不能被发现在你指定的长度的…'是添加到那个街区,
		 * 和阻塞继续直到所有文字都破损。
		 * @param	p_string
		 * @param	p_len
		 * @param	p_delim
		 * @return
		 */
		public static function block(p_string : String, p_len : uint, p_delim : String = ".") : Array
		{
			var arr:Array = new Array();
			if (p_string == null || !contains(p_string, p_delim)) 
			{
				return arr;	
			}
			var chrIndex:uint = 0;
			var strLen:uint = p_string.length;
			var replPatt:RegExp = new RegExp("[^" + escapePattern(p_delim) + "]+$");
			while (chrIndex <  strLen) 
			{
				var subString:String = p_string.substr(chrIndex, p_len);
				if (!contains(subString, p_delim))
				{
					arr.push(truncate(subString, subString.length));
					chrIndex += subString.length;
				}
				subString = subString.replace(replPatt, '');
				arr.push(subString);
				chrIndex += subString.length;
			}
			return arr;
		}
		
		/**
		 * Capitallizes第一个字在一个字符串或所有的单词。
		 * @param	p_string
		 * @param	...args
		 * @return
		 */
		public static function capitalize(p_string : String, ...args) : String
		{
			var str:String = trimLeft(p_string);
			if (args[0] === true)
			{
				return str.replace(/^.|\b./g, _upperCase);
			}
			else
			{
				return str.replace(/(^\w)/, _upperCase);
			}
		}
		
		/**
		 * 决定是否指定的字符串是p_char任何的实例。
		 * @param	p_string
		 * @param	p_char
		 * @return
		 */
		public static function contains(p_string : String, p_char : String) : Boolean
		{
			if (p_string == null)
			{
				return false;
			}
			return p_string.indexOf(p_char) != -1;
		}
		
		/**
		 * 决定的次数或sub-string士大夫中出现的字符串。
		 * @param	p_string
		 * @param	p_char
		 * @param	p_caseSensitive
		 * @return
		 */
		public static function countOf(p_string : String, p_char : String, p_caseSensitive : Boolean = true) : uint 
		{
			if (p_string == null) 
			{
				return 0;
			}
			var char : String = escapePattern(p_char);
			var flags : String = (!p_caseSensitive) ? 'ig' : 'g';
			return p_string.match(new RegExp(char, flags)).length;
		}
		
		/**
		 * Levenshtein距离(editDistance)是一个测量两个字符串的相似性,
		 * 距离是大量的缺失、插入、或替换要求
		 * p_source p_target变换成。
		 * @param	p_source
		 * @param	p_target
		 * @return
		 */
		public static function editDistance(p_source : String, p_target : String) : uint
		{
			var i:uint;
			if (p_source == null) 
			{ 
				p_source = ''; 
			}
			if (p_target == null) 
			{ 
				p_target = ''; 
			}
			if (p_source == p_target) 
			{
				return 0; 
			}
			var d : Array = new Array();
			var cost : uint;
			var n : uint = p_source.length;
			var m : uint = p_target.length;
			var j : uint;
			if (n == 0) 
			{ 
				return m; 
			}
			if (m == 0) 
			{ 
				return n; 
			}
			for (i = 0; i <= n; i++) 
			{ 
				d[i] = new Array(); 
			}
			for (i = 0; i <= n; i++) 
			{ 
				d[i][0] = i; 
			}
			for (j = 0; j <= m; j++) 
			{ 
				d[0][j] = j; 
			}
			for (i = 1; i <= n; i++) 
			{
				var s_i : String = p_source.charAt(i-1);
				for (j = 1; j <= m; j++) {
					var t_j : String = p_target.charAt(j-1);
					if (s_i == t_j) 
					{ 
						cost = 0; 
					}
					else 
					{ 
						cost = 1; 
					}
					d[i][j] = _minimum(d[i-1][j] + 1, d[i][j-1] + 1, d[i-1][j-1] + cost);
				}
			}
			return d[n][m];
		}
		
		/**
		 * 决定是否这个字符串以指定的后缀。
		 * @param	p_string
		 * @param	p_end
		 * @return
		 */
		public static function endsWith(p_string:String, p_end:String) : Boolean
		{
			return p_string.lastIndexOf(p_end) == p_string.length - p_end.length;
		}
		
		/**
		 * 决定是否这个字符串包含文本。
		 * @param	p_string
		 * @return
		 */
		public static function hasNext(p_string:String):Boolean 
		{
			var str:String = removeExtraWhitespace(p_string);
			return !!str.length;
		}
		
		/**
		 * 决定是否这个字符串包含任何字符。
		 * @param	p_string
		 * @return
		 */
		public static function isEmpty(p_string : String) : Boolean
		{
			if (p_string == null) 
			{
				return true;
			}
			return !p_string.length;
		}
		
		/**
		 * 决定是否这个字符串是数字。
		 * @param	p_string
		 * @return
		 */
		public static function isNumeric(p_string : String) : Boolean
		{
			if (p_string == null) 
			{ 
				return false; 
			}
			var regx:RegExp = /^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/;
			return regx.test(p_string);
		}
		
		/**
		 * p_string指定字符垫,给一个指定的长度从左边。
		 * @param	p_string
		 * @param	p_padChar
		 * @param	p_length
		 * @return
		 */
		public static function padLeft(p_string:String, p_padChar:String, p_length:uint) : String
		{
			var s:String = p_string;
			while (s.length < p_length) 
			{ 
				s = p_padChar + s; 
			}
			return s;
		}
		
		/**
		 * p_string指定字符垫,给一个指定的长度从右边。
		 * @param	p_string
		 * @param	p_padChar
		 * @param	p_length
		 * @return
		 */
		public static function padRight(p_string:String, p_padChar:String, p_length:uint) : String
		{
			var s:String = p_string;
			while (s.length < p_length) 
			{ 
				s += p_padChar; 
			}
			return s;
		}
		
		/**
		 * 正常情况下字符串句子格式”。
		 * @param	p_string
		 * @return
		 */
		public static function properCase(p_string : String) : String
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			var str:String = p_string.toLowerCase().replace(/\b([^.?;!]+)/, capitalize);
			return str.replace(/\b[i]\b/, "I");
		}
		
		/**
		 * 所有的角色都会逃一个字符串中去创造一个友好的“语录”刺
		 * @param	p_string
		 * @return
		 */
		public static function quote(p_string : String) : String
		{
			var regx:RegExp = /[\\"\r\n]/g;
			return '"'+ p_string.replace(regx, _quote) +'"'; 
		}
		
		/**
		 * 删除所有的实例字符串在移除输入的字符串。
		 * @param	p_string
		 * @param	p_remove
		 * @param	p_caseSensitive
		 * @return
		 */
		public static function remove(p_string:String, p_remove:String, p_caseSensitive:Boolean = true) : String
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			var rem:String = escapePattern(p_remove);
			var flags:String = (!p_caseSensitive) ? 'ig' : 'g';
			return p_string.replace(new RegExp(rem, flags), '');
		}
		
		/**
		 * 移除附加空白字符(空格换行符、回车符、制表符等)从指定的字符串。
		 * @param	p_string
		 * @return
		 */
		public static function removeExtraWhitespace(p_string:String) : String
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			var str:String = trim(p_string);
			return str.replace(/\s+/g, ' ');
		}
		
		/**
		 * 返回指定字符串性格相反顺序。
		 * @param	p_string
		 * @return
		 */
		public static function reverse(p_string : String) : String
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.split('').reverse().join('');
		}
		
		/**
		 * 返回指定字符串的逆向词序。
		 * @param	p_string
		 * @return
		 */
		public static function reverseWords(p_string : String) : String
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.split(/\s+/).reverse().join('');
		}
		
		/**
		 * 决定曾的百分比,根据editDistance
		 * @param	p_source
		 * @param	p_target
		 * @return
		 */
		public static function similarity(p_source:String, p_target:String) : Number
		{
			var ed:uint = editDistance(p_source, p_target);
			var maxLen:uint = Math.max(p_source.length, p_target.length);
			if (maxLen == 0) 
			{ 
				return 100; 
			}
			else 
			{ 
				return (1 - ed / maxLen) * 100; 
			}
		}
		
		/**
		 * 删除所有的< and >从基础标签一个字符串
		 * @param	p_string
		 * @return
		 */
		public static function stripTags(p_string:String):String 
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.replace(/<\/?[^>]+>/igm, '');
		}
		
		/**
		 * 互换套管的字符串。
		 * @param	p_string
		 * @return
		 */
		public static function swapCase(p_string:String):String 
		{
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.replace(/(\w)/, _swapCase);
		}
		
		/**
		 * 删除空白从前面和结束时指定的字符串。
		 * @param	p_string
		 * @return
		 */
		public static function trim(p_string:String):String {
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.replace(/^\s+|\s+$/g, '');
		}
		
		/**
		 * 删除空白从前面(左侧)指定的字符串。
		 * @param	p_string
		 * @return
		 */
		public static function trimLeft(p_string:String):String {
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.replace(/^\s+/, '');
		}
		
		/**
		 * 删除空白的结束(右端)指定的字符串。
		 * @param	p_string
		 * @return
		 */
		public static function trimRight(p_string:String):String {
			if (p_string == null) 
			{ 
				return ''; 
			}
			return p_string.replace(/\s+$/, '');
		}
		
		/**
		 * Determins单词的数量在一个字符串。
		 * @param	p_string
		 * @return
		 */
		public static function wordCount(p_string:String):uint {
			if (p_string == null) 
			{ 
				return 0; 
			}
			return p_string.match(/\b\w+\b/g).length;
		}
		
		/**
		 * 以字符串的形式返回到一个指定的长度缩短和随意的后缀
		 * @param	p_string
		 * @param	p_len
		 * @param	p_suffix
		 * @return
		 */
		public static function truncate(p_string : String, p_len : uint, p_suffix : String = "..."):String {
			if (p_string == null) 
			{ 
				return ''; 
			}
			p_len -= p_suffix.length;
			var trunc:String = p_string;
			if (trunc.length > p_len) 
			{
				trunc = trunc.substr(0, p_len);
				if (/[^\s]/.test(p_string.charAt(p_len))) 
				{
					trunc = trimRight(trunc.replace(/\w+$|\s+$/, ''));
				}
				trunc += p_suffix;
			}
			return trunc;
		}
		
		private static function escapePattern(p_pattern : String):String 
		{
			// RM: might expose this one, I've used it a few times already.
			return p_pattern.replace(/(\]|\[|\{|\}|\(|\)|\*|\+|\?|\.|\\)/g, '\\$1');
		}

		private static function _minimum(a:uint, b:uint, c:uint):uint 
		{
			return Math.min(a, Math.min(b, Math.min(c,a)));
		}

		private static function _quote(p_string:String, ...args):String 
		{
			switch (p_string) 
			{
				case "\\":
					return "\\\\";
				case "\r":
					return "\\r";
				case "\n":
					return "\\n";
				case '"':
					return '\\"';
				default:
					return '';
			}
		}

		private static function _upperCase(p_char:String, ...args):String 
		{
			return p_char.toUpperCase();
		}

		private static function _swapCase(p_char:String, ...args):String 
		{
			var lowChar:String = p_char.toLowerCase();
			var upChar:String = p_char.toUpperCase();
			switch (p_char) 
			{
				case lowChar:
					return upChar;
				case upChar:
					return lowChar;
				default:
					return p_char;
			}
		}
		
	}

}